home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2002 November / SGI Freeware 2002 November - Disc 1.iso / dist / fw_exmh.idb / usr / freeware / lib / exmh-2.5 / scan.tcl.z / scan.tcl
Text File  |  2002-07-08  |  10KB  |  349 lines

  1. # scan.tcl
  2. #
  3. # Folder scanning, with optimizations.
  4. #
  5. # Copyright (c) 1993 Xerox Corporation.
  6. # Use and copying of this software and preparation of derivative works based
  7. # upon this software are permitted. Any distribution of this software or
  8. # derivative works must comply with all applicable United States export
  9. # control laws. This software is made available AS IS, and Xerox Corporation
  10. # makes no warranty about the software, its performance or its conformity to
  11. # any specification.
  12.  
  13. #### Display folder contents
  14.  
  15. proc Scan_Folder {F {adjustDisplay 1}} {
  16.     Exmh_Debug Scan_Folder [time [list ScanFolder $F $adjustDisplay]]
  17. }
  18. proc ScanFolder {F adjustDisplay} {
  19.     global mhProfile flist ftoc exwin exmh
  20.  
  21.     if {[string compare $F $ftoc(folder)] == 0} {
  22.     Exmh_Debug Updating $F
  23.     set update 1    ;# Need to check for new messages.
  24.     set sameF 1    ;# Same folder as before
  25.     ScanAddLineInit
  26.     } else {
  27.     set sameF 0
  28.     set cacheFile $mhProfile(path)/$F/.xmhcache
  29.     if [catch {open $cacheFile} input] {
  30.         # No cache, scan last N messages
  31.         Exmh_Status "Limit scan $F last:$ftoc(scanSize) - Rescan?" warn
  32.         set input  [open "|$mhProfile(scan-proc) [list +$F] \
  33.             last:$ftoc(scanSize) -width $ftoc(scanWidth)"]
  34.         set ftoc(displayDirty) 1
  35.         set update 0
  36.     } else {
  37.         Exmh_Debug "loading .xmhcache"
  38.         set ftoc(displayDirty) 0
  39.         set update 1    ;# Need to check for new messages.
  40.     }
  41.     ScanAddLineReset $F
  42.     ScanAddLines [read $input]
  43.     catch {close $input}
  44.     }
  45.  
  46.     if {$update} {
  47.     # Add new messages to cached information
  48.     # Scan last message (again) plus any new messages
  49.     if {! $sameF} {
  50.         Ftoc_Reset [Widget_TextEnd $exwin(ftext)] {} $F
  51.     }
  52.     set id [Ftoc_MsgNumber [Ftoc_FindMsg {} last]]
  53.     if [catch {
  54.         Exmh_Debug Scanning new messages
  55.         set input [open "|$mhProfile(scan-proc) [list +$F] \
  56.             $id-last -width $ftoc(scanWidth)"]
  57.         set check [gets $input]
  58.         set new [read $input]
  59.         close $input
  60.     } err] {
  61.         # The last message no longer exists
  62.         Exmh_Debug No last msg $id: $err
  63.         } else {
  64.         set id2 [Ftoc_MsgNumberRaw $check]
  65.         if {$id2 == $id} {
  66.         # Last message still matches: add the new lines
  67.         ScanAddLines $new
  68.         set ftoc(displayDirty) 1
  69.         set update 0    ;# OK
  70.         } else {
  71.         Exmh_Debug "My last $id != $id2"
  72.         }
  73.     }
  74.     if {$update} {
  75.         # Something went wrong: rescan
  76.         if {[Ftoc_Changes "Scan Update Failed"] == 0} {
  77.         Exmh_Status "scan +$F last:$ftoc(scanSize)"
  78.         Background_Wait
  79.         set input  [open "|$mhProfile(scan-proc) [list +$F] \
  80.             last:$ftoc(scanSize) -width $ftoc(scanWidth)"]
  81.         set ftoc(displayDirty) 1
  82.         ScanAddLineReset $F
  83.         ScanAddLines [read $input]
  84.         catch {close $input}
  85.         }
  86.     }
  87.     }
  88.     ScanAddLineCleanup $F
  89.     if {! $sameF} {
  90.     Msg_Reset [Widget_TextEnd $exwin(ftext)] $F
  91.     } else {
  92.     Ftoc_Update [Widget_TextEnd $exwin(ftext)] $F
  93.     }
  94.     set ftoc(displayValid) 1
  95.     if {$adjustDisplay} {
  96.     Ftoc_Yview end
  97.     }
  98.     if {$update} {
  99.     Flist_ForgetUnseen $F
  100.     }
  101.     Ftoc_ShowUnseen $F
  102.     return
  103. }
  104. proc Scan_FolderForce {{F ""}} {
  105.     global exmh mhProfile ftoc
  106.     if {$F == ""} {
  107.     set F $exmh(folder)
  108.     }
  109.     set cacheFile $mhProfile(path)/$F/.xmhcache
  110.     if {$F == ""} {
  111.     Exmh_Status "No current folder" red
  112.     } elseif {$F != $exmh(folder)} {
  113.     # If we aren't currently viewing the folder, just delete
  114.     # the cache file and we'll take care of this later
  115.     Exmh_Debug "Clearing $cacheFile"
  116.     file delete $cacheFile
  117.     } elseif {! [Ftoc_Changes Rescan]} {
  118.     Background_Wait
  119.     Label_Folder $F
  120.     Exmh_Status "rescanning $F ..."
  121.     Scan_IO $F [open "|$mhProfile(scan-proc) [list +$F] \
  122.         -width $ftoc(scanWidth)"]
  123.     set ftoc(displayValid) 1
  124.     set ftoc(displayDirty) 1
  125.     Ftoc_Yview end
  126.     Flist_ForgetUnseen $F
  127.     Ftoc_ShowUnseen $F
  128.     Exmh_Status ok
  129.     }
  130. }
  131. proc Scan_FolderUpdate { f } {
  132.     global ftoc
  133.  
  134.     if !$ftoc(displayValid) {
  135.         return                  ;#  don't update pseudo-displays
  136.     }
  137.     Label_Folder $f
  138.     Scan_Folder $f 0
  139. }
  140. proc Scan_Iterate { incout lineVar body } {
  141.     upvar $lineVar line
  142.     foreach line [split $incout \n] {
  143.     if [regexp ^Incorporating $line] {
  144.         continue
  145.     }
  146.     if {[string length $line] > 0} {
  147.         uplevel $body
  148.     }
  149.     }
  150. }
  151.  
  152. proc Scan_Inc {folder incOutput} {
  153.     global exwin ftoc
  154.     # Append output of an Inc to the scan display
  155.     ScanAddLineInit
  156.     Scan_Iterate $incOutput l {
  157.     ScanAddLine $l
  158.     }
  159.     ScanAddLineCleanup $folder
  160.     Ftoc_Update [Widget_TextEnd $exwin(ftext)] $folder
  161.     set ftoc(displayDirty) 1
  162.     if {$ftoc(showNew)} {
  163.     Ftoc_Yview end
  164.     }
  165.     # Don't forget unseen here, just find recently added unseen messages
  166.     Ftoc_ShowUnseen $folder
  167.     Label_Folder $folder
  168. }
  169. proc Scan_IO {folder scanIO } {
  170.     Exmh_Debug Scan_IO [time [list ScanIO $folder $scanIO]]
  171. }
  172. proc ScanIO {folder scanIO } {
  173.     global exmh exwin
  174.  
  175.     ScanAddLineReset $folder
  176.     if [catch {
  177.     ScanAddLines [read $scanIO]
  178.     close $scanIO
  179.     } err] {
  180.     Exmh_Status $err red
  181.     catch {close $scanIO}
  182.     }
  183.     ScanAddLineCleanup $folder
  184.     Msg_Reset [Widget_TextEnd $exwin(ftext)] $folder
  185. }
  186.  
  187. proc ScanAddLineInit {} {
  188.     global exmh exwin
  189.     $exwin(ftext) configure -state normal
  190. }
  191. proc ScanAddLineReset { folder } {
  192.     global exwin ftoc
  193.     if {$ftoc(folder) == $folder} {
  194.     # Rescanning a folder, so save mark state
  195. #    Ftoc_Save $folder
  196.     }
  197.     ScanAddLineInit
  198.     $exwin(ftext) delete 0.0 end
  199.     update idletasks
  200. }
  201. proc ScanAddLine { line } {
  202.     global exwin
  203.     $exwin(ftext) insert end "$line\n"
  204. }
  205. proc ScanAddLines { text } {
  206.     global exwin
  207.     $exwin(ftext) insert end $text
  208. }
  209. proc ScanAddLineCleanup { folder } {
  210.     global exwin flist ftoc
  211.     if {$ftoc(folder) == $folder} {
  212.     # Restore mark state
  213. #    Ftoc_Restore $folder
  214.     }
  215.     set ftoc(folder) $folder
  216.     $exwin(ftext) configure -state disabled
  217. }
  218. proc Scan_ProjectSelection { ids } {
  219.     global ftoc exwin
  220.     set lines {}
  221.     set num 0
  222.     foreach id $ids {
  223.     set L [Ftoc_FindMsg $id]
  224.     if {$L != {}} {
  225.         lappend lines [$exwin(ftext) get $L.0 $L.end]
  226.         incr num
  227.     }
  228.     }
  229.     set ftoc(displayValid) 0    ;# Don't cache this display
  230.     ScanAddLineReset $ftoc(folder)
  231.     foreach line $lines {
  232.     ScanAddLine $line
  233.     }
  234.     ScanAddLineCleanup $ftoc(folder)
  235.     Msg_ClearCurrent
  236.     Msg_Reset $num
  237. }
  238. proc Scan_CacheValid {F} {
  239.     # Maintain a cache of folder listings
  240.     global mhProfile exmh
  241.     set cacheFile $mhProfile(path)/$F/.xmhcache
  242.     if {![file exists $cacheFile] || ![file size $cacheFile]} {
  243.     return 0
  244.     }
  245.     if {[file mtime $mhProfile(path)/$F] >
  246.     [file mtime $cacheFile]} {
  247.     return 0
  248.     }
  249.     return 1
  250. }
  251. proc Scan_CacheUpdate {} {
  252.     global exmh mhProfile exwin ftoc
  253.     set folder $exmh(folder)
  254.     if {$folder == {}} {
  255.     return
  256.     }
  257.     if !$ftoc(displayDirty) {
  258.     return
  259.     }
  260.     set cacheFile $mhProfile(path)/$folder/.xmhcache
  261.  
  262. #
  263. # Display is invalid but changes (deletes) still must be reflected in cache. 
  264. # A full rescan is the penalty you have to pay for deleting messages inside 
  265. # this thing.
  266. #
  267.     if !$ftoc(displayValid) {
  268.     set curLine [Ftoc_ClearCurrent]            ;# Clear +
  269.         if [file writable $cacheFile] {
  270.             set scancmd "exec $mhProfile(scan-proc) [list +$folder] \
  271.             -width $ftoc(scanWidth) > [list $cacheFile]"
  272.             if [catch $scancmd err] {
  273.                 Exmh_Status "failed to rescan folder $folder: $err" warn
  274.             }
  275.         }
  276.     Ftoc_Change [Ftoc_MsgNumber $curLine] $curLine    ;# Restore it
  277.     } elseif [catch {
  278.     set cacheIO [open $cacheFile w]
  279.     set curLine [Ftoc_ClearCurrent]            ;# Clear +
  280.     set display [$exwin(ftext) get 1.0 "end -1 char"]
  281.     Ftoc_Change [Ftoc_MsgNumber $curLine] $curLine    ;# Restore it
  282.     puts $cacheIO $display nonewline
  283.     close $cacheIO
  284.     set ftoc(displayDirty) 0
  285.     } err] {
  286.     Exmh_Debug Scan_CacheUpdate error $err
  287.     catch {close $cacheIO}
  288.     }
  289. }
  290.  
  291. # Move scan lines to the scan cache for another folder
  292. proc Scan_Move { folder scanlinesR new } {
  293.     global mhProfile
  294.     set cacheFile $mhProfile(path)/$folder/.xmhcache
  295.     if ![file writable $cacheFile] {
  296.     Exmh_Debug Scan_Move $folder scan cache not writable
  297.     return
  298.     }
  299.     # Reverse engineer the scan format
  300.     if ![regexp {( *)([0-9]+)} [lindex $scanlinesR 0] prefix foo2 number] {
  301.     Exmh_Debug Scan_Move cannot handle scan format
  302.     return
  303.     }
  304.     set len [string length $prefix]
  305.     set fmt [format "%%%dd%%s" $len]
  306.     set cacheIO [open $cacheFile a]
  307.     for {set i [expr [llength $scanlinesR]-1]} {$i >= 0} {incr i -1} {
  308.     set line [lindex $scanlinesR $i]
  309.     if [regsub {( *[0-9]+)(\+)} $line {\1 } newline] {
  310.         puts $cacheIO [format $fmt $new [string range $newline $len end]] \
  311.         nonewline
  312.     } else {
  313.         puts $cacheIO [format $fmt $new [string range $line $len end]] \
  314.         nonewline
  315.     }
  316.     incr new
  317.     }
  318.     close $cacheIO
  319. }
  320. proc Scan_AllFolders { {force 0} } {
  321.     global flist mhProfile ftoc wish
  322.     if [catch {open [Env_Tmp]/scancmds w} out] {
  323.     Exmh_Status "Scan_AllFolders $out"
  324.     return
  325.     }
  326.     set ctx [Env_Tmp]/scanctx
  327.     puts $out "wm withdraw ."
  328.     set myname [winfo name .]
  329.     puts $out "catch \{ exec touch $ctx.\[pid\] \}"
  330.     puts $out "set env(MHCONTEXT) $ctx.\[pid\]"
  331.     foreach f $flist(allfolders) {
  332.     if {$force || ! [Scan_CacheValid $f]} {
  333.         puts $out "catch \{send $myname \{Exmh_Status \"scan +$f\"\}\}"
  334.         puts $out "catch {
  335.         set out \[open $mhProfile(path)/$f/.xmhcache w $mhProfile(msg-protect)\]
  336.         exec $mhProfile(scan-proc) +$f -width $ftoc(scanWidth) -noheader >@\$out
  337.         close \$out
  338.         }"
  339.     }
  340.     }
  341.     puts $out "catch \{send $myname \{Exmh_Status \"scans completed\"\}\}"
  342.     puts $out "exec rm $ctx.\[pid\]"
  343.     puts $out exit
  344.     close $out
  345.     Exmh_Status "wish -f [Env_Tmp]/scancmds &" blue
  346.     exec $wish -f [Env_Tmp]/scancmds &
  347. }
  348.